package com.stm.bi.report;

import com.stm.bi.constant.PlanConstants;
import com.stm.bi.core.util.DateUtils;
import com.stm.bi.dto.query.ods.OdsProductInventoryQry;
import com.stm.bi.jdbc.JdbcUtil;
import com.stm.bi.model.DatatablePage;
import com.stm.bi.model.DateRange;
import com.stm.bi.model.RowData;
import com.stm.bi.model.Title;
import com.stm.framework.core.context.UserHolder;
import com.stm.framework.core.util.FileResourceLoader;
import com.stm.framework.dbcp.JdbcService;
import com.stm.framework.dto.Response;
import com.stm.framework.model.CustomizePage;
import com.stm.saas.api.WarehouseRemoteService;
import com.stm.saas.dto.query.WarehousePageQry;
import com.stm.saas.dto.vo.WarehouseQueryVO;
import com.stm.saas.dto.vo.WarehouseRecordVO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

/**
 * 仓库信息-查询执行器
 *
 * @author zhouyuanpeng
 * @date 2023-10-17
 */
@Component
public class WarehouseQueryExe {

    @Resource
    private WarehouseRemoteService warehouseRemoteService;

    private final JdbcService jdbcService = JdbcUtil.getOdsJdbcService();

    /**
     * 查询页面
     *
     * @param warehousePageQry
     */
    public Response<CustomizePage<WarehouseQueryVO>> selectPage(WarehousePageQry warehousePageQry){
        Response<CustomizePage<WarehouseQueryVO>> res = warehouseRemoteService.selectInfoPage(warehousePageQry);
        if (!res.isSuccess()) {
            return res;
        }

        List<String> warehouseCodes = res.get().getRecords().stream().map(WarehouseQueryVO::getCode).toList();

        OdsProductInventoryQry odsProductInventoryQry = this.getOdsProductInventory(warehousePageQry.getDateStr(), warehousePageQry.getDateStr(), PlanConstants.TYPE_MONTH);

        odsProductInventoryQry.setWarehouseCodeList(warehouseCodes);

        List<Map> maps = this.selectProductInventory(odsProductInventoryQry);

        Map<String, Map> warehouseMap = maps.stream().collect(Collectors.toMap(map -> (String) map.get("warehouse_code"), map -> map));

        for (WarehouseQueryVO record : res.get().getRecords()) {
            // 补充记录
            if (warehouseMap.containsKey(record.getCode())) {
                Map dataMap = warehouseMap.get(record.getCode());
                record.setInWarehouseQty(this.getWanNum("in_warehouse_qty", dataMap));
                record.setSaleOutQty(this.getWanNum("sale_out_qty", dataMap));
                record.setPeriodEndQty(this.getWanNum("period_end_qty", dataMap));
            }
        }
        return res;
    }

    /**
     * 数据转万件单位
     * @param qtyFieldName
     * @param dataMap
     * @return
     */
    private BigDecimal getWanNum(String qtyFieldName, Map dataMap) {
        Long qry = (Long) dataMap.get(qtyFieldName);
        if (qry == null) {
            return null;
        } else {
            return new BigDecimal(qry).divide(new BigDecimal(10000));
        }
    }


    private OdsProductInventoryQry getOdsProductInventory(String startDate, String endDate, String dateType) {
        OdsProductInventoryQry qry = new OdsProductInventoryQry();
        if (PlanConstants.TYPE_MONTH .equals(dateType)) {
            qry.setStartDate(startDate.substring(0, 7) + "-01");
            DateRange dateRange = DateUtils.getDayFirstAndEnd(endDate, 1, 1);
            qry.setEndDate(dateRange.getEndDate());
        } else if(PlanConstants.TYPE_YEAR .equals(dateType)) {
            qry.setStartDate(startDate.substring(0, 4)  + "-01-01");
            DateRange dateRange = DateUtils.getDayFirstAndEnd(endDate, 1, 1);
            qry.setEndDate(dateRange.getEndDate());
        } else {
            qry.setStartDate(startDate);
            qry.setEndDate(endDate);
        }
        return qry;
    }

    private List<Map> selectProductInventory(OdsProductInventoryQry qry) {

        String selectSql = FileResourceLoader.getResourceAsString("/sql/warehouseData.sql");

        String warehouseCodeStr = qry.getWarehouseCodeList().stream().map(item -> "'" + item + "'").collect(Collectors.joining(","));
        if(warehouseCodeStr.isEmpty()) {
            selectSql = selectSql.replace("AND warehouse_code IN (?)", "");
        } else {
            selectSql = selectSql.replace("IN (?)", "IN (" + warehouseCodeStr + ")");
        }


        List<Map> maps = jdbcService.selectList(selectSql, new Object[]{
                UserHolder.getLoginUser().getOrgNo(),
                qry.getStartDate(),
                qry.getEndDate()});

        return maps;
    }

    public Response<DatatablePage> selectWarehouseInventory(String warehouseCode, String year) {
        OdsProductInventoryQry qry = this.getOdsProductInventory(year, year, PlanConstants.TYPE_YEAR);
        qry.setWarehouseCode(warehouseCode);
        List<Map> maps = this.selectProductInventoryMonth(qry);
        DatatablePage datatablePage = new DatatablePage();
        datatablePage.getTitles().add(new Title().setCode("date").setName("操作时间"));
        datatablePage.getTitles().add(new Title().setCode("inWarehouseQty").setName("进货量（万件）"));
        datatablePage.getTitles().add(new Title().setCode("saleOutQty").setName("销量（万件）"));
        datatablePage.getTitles().add(new Title().setCode("periodEndQty").setName("库存量（万件）"));

        datatablePage.setSize(10000L);

        Map<String, Map> dataMap = maps.stream().collect(Collectors.toMap(map -> (String) map.get("month"), map -> map));

        List<RowData> rowDataList = new ArrayList<>();
        List<String> dateList = DateUtils.getDateList(qry.getStartDate(), qry.getEndDate(), PlanConstants.TYPE_MONTH);
        for (String date : dateList) {
            RowData rowData = new RowData();
            rowData.put("date", date);
            Map map = dataMap.get(date);
            if (map != null) {
                rowData.put("inWarehouseQty", this.getWanNum("in_warehouse_qty", map));
                rowData.put("saleOutQty",this.getWanNum("sale_out_qty", map));
                rowData.put("periodEndQty",this.getWanNum("period_end_qty", map));
            }
            rowDataList.add(rowData);
        }

        datatablePage.setDatas(rowDataList);

        return Response.of(datatablePage);
    }

    private List<Map> selectProductInventoryMonth(OdsProductInventoryQry qry) {

        String selectSql = FileResourceLoader.getResourceAsString("/sql/warehouseDataMonth.sql");
        List<Map> maps = jdbcService.selectList(selectSql, new Object[]{
                UserHolder.getLoginUser().getOrgNo(),
                qry.getStartDate(),
                qry.getEndDate(),
                qry.getWarehouseCode()});

        return maps;
    }
}
